package com.zzyl.service.impl;

import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.properties.WeChatProperties;
import com.zzyl.service.WeChatService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

/**
 * @className: WeChatServiceImpl
 * @description:
 * @author: InnovatorX
 * @date: 2024/5/29 14:37
 * @Version: 1.0
 */
@Service
@Slf4j
public class WeChatServiceImpl implements WeChatService {
    @Autowired
    private WeChatProperties weChatProperties;

    //调用微信接口,获取openId  GET https://api.weixin.qq.com/sns/jscode2session
    private final String GET_OPEN_ID_URL = "https://api.weixin.qq.com/sns/jscode2session";

    // 调用微信接口(获取accessToken的路径) GET https://api.weixin.qq.com/cgi-bin/token
    private final String GET_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token";

    // 获取手机号的路径 POST https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=ACCESS_TOKEN
    private final String GET_POST_PHONE_NUMBER_URL = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=";

    /**
     * @description: 获取openId
     * @param: [code]
     * @return: java.lang.String
     * @author: InnovatorX
     * @date: 2024/5/29 14:38
     */
    @Override
    public String getOpenId(String code) {
        // 获取微信配置
        Map<String, Object> parmMap = getWeChatParmMap();
        parmMap.put("js_code", code);
        parmMap.put("grant_type", "authorization_code");
        // 调用微信接口
        String jsonStr = HttpUtil.get(GET_OPEN_ID_URL, parmMap);
        log.info("微信接口返回数据:{}", jsonStr);
        // 把json字符串转换为json对象
        JSONObject jsonObject = JSONUtil.parseObj(jsonStr);
        if (jsonStr == null) {
            log.error("微信接口返回(openid)数据失败");
            throw new BaseException(BasicEnum.GET_OPENID_ERROR);
        }
        String openid = jsonObject.getStr("openid");
        log.info("openid:{}", openid);
        return openid;
    }

    @Override
    public String getPhoneNumber(String phoneCode) {
        // 获取access_token
        String accessToken = getAccessToken();
        HashMap<String, Object> parmMap = new HashMap<>();
        parmMap.put("code", phoneCode);

        // 获取手机号
        String jsonStr = HttpUtil.post(GET_POST_PHONE_NUMBER_URL + accessToken, JSONUtil.toJsonStr(parmMap));
        log.info("微信接口返回手机号数据:{}", jsonStr);
        // json转对象
        JSONObject jsonObject = JSONUtil.parseObj(jsonStr);
        if (jsonObject.get("phone_info") == null) {
            log.error("获取手机号数据失败");
            throw new BaseException(BasicEnum.GET_PHONE_ERROR);
        }
        JSONObject phoneInfo = jsonObject.getJSONObject("phone_info");
        if (phoneInfo == null){
            log.error("获取手机号数据失败");
            throw new BaseException(BasicEnum.GET_PHONE_ERROR);
        }
        String phoneNumber = phoneInfo.getStr("phoneNumber");
        log.info("手机号:{}", phoneNumber);

        return phoneNumber;
    }

    /**
     * 获取微信访问Token
     * @return
     */
    private String getAccessToken() {
        // 调用微信接口获取token
        Map<String, Object> parmMap = getWeChatParmMap();
        parmMap.put("grant_type", "client_credential");
        log.info("微信接口返回数据:{}", parmMap);
        String jsonStr = HttpUtil.get(GET_ACCESS_TOKEN_URL, parmMap);
        // 检查jsonStr是否为null，确保后续操作的有效性
        if (jsonStr == null) {
            // 记录错误日志并抛出获取微信访问令牌错误的异常
            log.error("微信接口返回(access_token)数据失败");
            throw new BaseException(BasicEnum.GET_WECHAT_ACCESS_TOKEN_ERROR);
        }

        // json转对象
        JSONObject jsonObject = JSONUtil.parseObj(jsonStr);
        if (jsonObject.get("access_token") == null){
            log.error("微信接口返回(access_token)数据失败");
            throw new BaseException(BasicEnum.GET_WECHAT_ACCESS_TOKEN_ERROR);
        }
        String accessToken = jsonObject.getStr("access_token");
        log.info("access_token:{}", accessToken);
        return accessToken;
    }

    /**
     * 获取微信参数映射表
     * 该方法不接受任何参数，返回一个包含微信接口调用必要参数的Map对象。
     *
     * @return Map<String, Object> - 包含appid和secret的键值对映射表
     */
    private Map<String, Object> getWeChatParmMap() {
        // 创建一个HashMap用于存放微信接口调用的参数
        HashMap<String, Object> hashMap = new HashMap<>();
        // 将微信配置中的AppID和Secret添加到Map中
        hashMap.put("appid", weChatProperties.getAppId());
        hashMap.put("secret", weChatProperties.getSecret());
        return hashMap;
    }
}
